package querybuilder

import (
	"fmt"
	"strings"
)

type AndOr string

func (s *AndOr) IsOr() {
	*s = "OR"
}

func (s *AndOr) IsAnd() {
	*s = "AND"
}

type ConditionItem struct {
	Field string
	Expr  string
	Value interface{}
}

func (s *ConditionItem) SetField(field string) *ConditionItem {
	s.Field = field
	return s
}

func (s *ConditionItem) SetValue(value interface{}) *ConditionItem {
	s.Value = value
	return s
}

func (s *ConditionItem) SetExpr(expr string) *ConditionItem {
	s.Expr = expr
	return s
}

func (s *ConditionItem) String() string {
	return fmt.Sprintf("%s %s %s", s.Field, s.Expr, s.Value)
}

type ConditionStage struct {
	AndOr AndOr
	//Items []fmt.Stringer
	//Stages []fmt.Stringer
	Items  []*ConditionItem
	Stages []*ConditionStage
}

func (s *ConditionStage) IsOr() *ConditionStage {
	s.AndOr.IsOr()
	return s
}

func (s *ConditionStage) IsAnd() *ConditionStage {
	s.AndOr.IsAnd()
	return s
}

func (s *ConditionStage) AddItem(item *ConditionItem) *ConditionStage {
	s.Items = append(s.Items, item)
	return s
}

func (s *ConditionStage) AddStage(stage *ConditionStage) *ConditionStage {
	s.Stages = append(s.Stages, stage)
	return s
}

func (s *ConditionStage) NewItem(args ...string) *ConditionItem {
	item := new(ConditionItem)
	if len(args) == 3 {
		item.SetField(args[0]).SetExpr(args[1]).SetValue(args[2])
	}
	if len(args) == 3 {
		item.SetField(args[0]).SetExpr(Expr_Eq).SetValue(args[1])
	}
	s.AddItem(item)
	return item
}

func (s *ConditionStage) NewStage(filler func(stage *ConditionStage)) *ConditionStage {
	stage := new(ConditionStage)
	filler(stage)
	s.AddStage(stage)
	return stage
}

func (s *ConditionStage) String() string {
	items := make([]string, 0)
	for _, i := range s.Items {
		items = append(items, i.String())
	}
	for _, s := range s.Stages {
		items = append(items, fmt.Sprintf("( %s )", s.String()))
	}
	return strings.Join(items, fmt.Sprintf(" %s ", s.AndOr))
}

type Condition struct{}
